import argparse
import json
import logging
import os
import time
import uuid
import asyncio
from contextlib import asynccontextmanager
from typing import Optional
from urllib.parse import quote

import uvicorn
from fastapi import (
    FastAPI,
    File,
    Form,
    HTTPException,
    Query,
    Request,
    UploadFile,
    WebSocket,
    WebSocketDisconnect,
)
from fastapi.middleware.cors import CORSMiddleware
from fastapi.openapi.docs import get_swagger_ui_html
from fastapi.responses import JSONResponse, StreamingResponse
from fastapi.staticfiles import StaticFiles

from params_type import (
    ApproveRequest,
    CreateTeamRequest,
    ExitTeamRequest,
    ReadAllRequest,
    TeamMsgReadRequest,
    UpdateTeamRequest,
    MobileUserRequest,
    UpdateMobileUserRequest,
)
from service import (
    add_friend_request,
    approve_friendship,
    create_team,
    get_friendship,
    get_session_list,
    get_team_info,
    get_team_message,
    get_user_message_history,
    get_user_teams,
    get_users,
    get_uts,
    send_msg_to_team,
    send_msg_to_user,
    team_message_readed,
    update_team,
    upsert_friendship,
    mobile_user_sign_up,
    mobile_user_sign_in,
    mobile_user_update,
)
from utils import ConnectionManager, DatabaseOperator

# 配置全局变量
UPLOAD_DIR = "./uploads"
MAX_UPLOAD_BYTES = 100 * 1024 * 1024
CHUNK_SIZE = 1024 * 1024
PROGRESS_STEP_PERCENT = 5


# 配置应用日志
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)

# 创建应用专用logger
app_logger = logging.getLogger("message_server")


@asynccontextmanager
async def lifespan(app: FastAPI):
    # 应用启动时执行
    app_logger.info("app starting to run some initialization work...")
    # 初始化数据库连接
    db = DatabaseOperator(pool_size=20)
    manager = ConnectionManager(db)

    # Add to app state
    app.state.db = db
    app.state.manager = manager

    task = asyncio.create_task(heartbeat_checker(manager, app_logger))
    app.state.check_task = task
    yield
    # 应用关闭时执行
    app_logger.info("app is shutting down...")

    if hasattr(app.state, 'check_task') and not app.state.check_task.done():
        app.state.check_task.cancel()
        try:
            await asyncio.wait_for(app.state.check_task, timeout=5.0)  # 5秒超时
        except asyncio.TimeoutError:
            app_logger.warning("Heartbeat checker task did not stop in time")
        except asyncio.CancelledError:
            pass  # 正常取消
        except Exception as e:
            app_logger.error(f"Error stopping heartbeat checker: {e}")

    # 关闭所有活动的WebSocket连接
    if hasattr(app.state.manager, "active_connections"):
        active_sockets = list(app.state.manager.active_connections.items())
        for socket_id, websocket in active_sockets:
            try:
                await websocket.close()
                app_logger.info(f"已关闭WebSocket连接: {socket_id}")
            except Exception as e:
                app_logger.info(f"关闭WebSocket连接{socket_id}时出错: {str(e)}")
        app.state.manager.active_connections.clear()

    # 修改用户状态为offline
    online_users = app.state.db.get_all("User", {"status": "online"})
    for user in online_users:
        app.state.db.update_one("User", {"status": "offline"}, {"id": user["id"]})

    # 关闭数据库连接
    if app.state.db._is_connected:
        app.state.db.close()


app = FastAPI(
    lifespan=lifespan,
    title="HAIant Private Cloud APIs",
    description="A message management service for HAIant Private Cloud",
    version="0.1.0",
    docs_url=None,
    redoc_url=None,
)

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.mount("/static", StaticFiles(directory="static"), name="static")


@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
    return JSONResponse(
        status_code=500,
        content={
            "status": "error",
            "code": 500,
            "message": "Internal Server Error",
            "details": str(exc),
        },
    )


@app.get("/docs", include_in_schema=False)
async def custom_swagger_ui_html():
    return get_swagger_ui_html(
        openapi_url=app.openapi_url,
        title=app.title + " - Swagger UI",
        swagger_js_url="/static/swagger-ui/swagger-ui-bundle.js",
        swagger_css_url="/static/swagger-ui/swagger-ui.css",
    )


@app.get("/check")
def check():
    """
    检查服务是否能正确响应

    返回示例:
    {"message": "success"}
    """
    try:
        return {"message": "success"}
    except Exception as e:
        return {"message": "error", "details": str(e)}


@app.get("/unread")
def unread(mac_addr: str):
    """
    查询总的未读消息数

    参数:
    - mac_addr: 用户的MAC地址

    返回示例:
    {"message": "success", "data": int}
    """
    try:
        count1 = app.state.db.get_count("Message", {"target": mac_addr, "status": "unread"})

        user_info = app.state.db.get_one("User", {"mac_addr": mac_addr})
        user_teams = app.state.db.get_all("User_Team", {"user_id": user_info.get("id")})
        team_ids = [team.get("team_id") for team in user_teams]
        team_msg_count = app.state.db.get_count("Team_Message", {"team_id": team_ids})

        readed = [
            app.state.db.get_count(
                "Team_Message_Read",
                {"team_id": team_id, "user_id": user_info.get("id")},
            )
            for team_id in team_ids
        ]

        return {"message": "success", "data": count1 + team_msg_count - sum(readed)}
    except Exception as e:
        return {"message": "error", "details": str(e)}


@app.get("/v1/session")
def get_session(mac_addr: str):
    """
    获取用户的历史消息列表

    Args:
        mac_addr (str): _description_
    """
    try:
        session_list = get_session_list(app.state.db, app_logger, {"mac_addr": mac_addr})
        return {"message": "success", "data": session_list}
    except Exception as e:
        return {"message": "error", "details": str(e)}


@app.get("/v1/friends")
def get_friends(mac_addr: str, name: str = None):
    """
    获取用户的好友和群聊列表以及未读消息数

    参数：
    - mac_addr: 用户的MAC地址 （排除自己）
    - name: 用户名（可选，模糊搜索）

    返回示例:
    {
        "message": "success",
        "data": [
            {
                "id": 5,
                "name": "Group1012-1dd",
                "created_at": "2025-10-12 11:04:30",
                "category": "team",
                "unread": 0,
                "users": 3,
                "_id": "team_5"
            },
            {
                "id": 2,
                "name": "张云龙(Mac)",
                "mac_addr": "ba:4a:9a:67:c0:69",
                "socket_id": "0f850596-92c6-4936-b8c7-5db6a6d5dc9e",
                "status": "offline",
                "created_at": "2025-08-11 15:55:40",
                "unread": 0,
                "category": "user",
                "_id": "user_2"
            }
        ]
    }
    """
    try:
        data = get_friendship(app.state.db, app_logger, {"mac_addr": mac_addr, "name": name})
        return {"message": "success", "data": data}
    except Exception as e:
        return {"message": "error", "details": str(e)}


@app.get("/uts")
def users_teams(mac_addr: str, name: str = None):
    """
    获取用户列表(包括了私聊和群聊)，和未读消息数

    参数：
    - mac_addr: 用户的MAC地址 （排除自己）
    - name: 用户名（可选，模糊搜索）

    返回示例:
    {
        "message": "success",
        "data": [
            {
                "id": 5,
                "name": "Group1012-1dd",
                "created_at": "2025-10-12 11:04:30",
                "category": "team",
                "unread": 0,
                "users": 3,
                "_id": "team_5"
            },
            {
                "id": 2,
                "name": "张云龙(Mac)",
                "mac_addr": "ba:4a:9a:67:c0:69",
                "socket_id": "0f850596-92c6-4936-b8c7-5db6a6d5dc9e",
                "status": "offline",
                "created_at": "2025-08-11 15:55:40",
                "unread": 0,
                "category": "user",
                "_id": "user_2"
            }
        ]
    }
    """
    try:
        data = get_uts(app.state.db, app_logger, {"mac_addr": mac_addr, "name": name})
        return {"message": "success", "data": data}
    except Exception as e:
        return {"message": "error", "details": str(e)}


@app.post("/v1/friend/approve")
def friend_approve(request: ApproveRequest):
    """
    同意好友申请

    Args:
        request (AddFriendRequest): _description_
        source: str (mac_addr)
        target: str (mac_addr)
    """
    try:
        approve_friendship(app.state.db, app_logger, request)
        return {"message": "success"}
    except Exception as e:
        return {"message": "error", "details": str(e)}


@app.post("/v1/friend/update")
def approve_friend_request(request: ApproveRequest):
    """
    更新好友备注请求

    Args:
        request (AddFriendRequest): _description_
        source: str (mac_addr)
        target: str (mac_addr)
    """
    try:
        upsert_friendship(app.state.db, app_logger, request)
        return {"message": "success"}
    except Exception as e:
        return {"message": "error", "details": str(e)}


@app.get("/user")
def user_list(mac_addr: str, name: str = None):
    """
    获取用户列表，和未读消息数

    参数：
    - mac_addr: 用户的MAC地址 （排除自己）
    - name: 用户名（可选，模糊搜索）

    返回示例:
    {
        "message": "success",
        "data": [
            {
                "id": 2,
                "name": "张云龙(Mac)",
                "mac_addr": "ba:4a:9a:67:c0:69",
                "socket_id": "0f850596-92c6-4936-b8c7-5db6a6d5dc9e",
                "status": "offline",
                "created_at": "2025-08-11 15:55:40",
            }
        ]
    }
    """
    try:
        data = get_users(app.state.db, app_logger, {"mac_addr": mac_addr, "name": name})
        return {"message": "success", "data": data}
    except Exception as e:
        return {"message": "error", "details": str(e)}


@app.post("/read/{id}")
def read_message(id: int):
    """
    更新私聊消息状态为已读

    参数：
    - id: 消息ID

    返回示例:
    {"message": "success"}
    """
    try:
        app_logger.info("更新消息状态为已读")
        app.state.db.update_one("Message", {"status": "read"}, {id: int(id)})

        return {"message": "success"}
    except Exception as e:
        return {"message": "error", "details": str(e)}


@app.post("/team/msg/read")
def read_message(request: TeamMsgReadRequest):
    """
    用户读取了团队消息

    参数：
    - msg_id: 消息ID
    - team_id: 群ID
    - mac_addr: 用户MAC地址

    返回示例:
    {"message": "success", data: {"team_message_id": id}}
    """
    try:
        data = team_message_readed(app.state.db, app_logger, request)
        return {"message": "success", "data": data}
    except Exception as e:
        return {"message": "error", "details": str(e)}


@app.post("/readall")
def read_all_message(request: ReadAllRequest):
    """
    批量更新私聊消息状态为已读（暂时用不上，因为在查询私聊消息时已经更新了状态）
    """
    try:
        rows = app.state.db.update_many(
            "Message",
            {"status": "read"},
            {"source": request.source, "target": request.target},
        )

        return {"message": "success", "count": rows}
    except Exception as e:
        return {"message": "error", "details": str(e)}


@app.get("/history")
def get_message(id_1: str, id_2: str):
    """
    获取两个用户之间的通信记录, id_1 为用户本身。

    参数：
    - id_1: 用户1的MAC地址
    - id_2: 用户2的MAC地址

    返回示例:
    {"message": "success", "data": [
        {
            "id": 140,
            "source": "ba:4a:9a:67:c0:69",
            "target": "24:b2:b9:54:44:82",
            "context": "user message unread",
            "status": "read",
            "created_at": "2025-10-13 01:52:18",
            "file_id": null,
            "target_name": "张云龙(Mac)"
        },
        {
            "id": 139,
            "source": "ba:4a:9a:67:c0:69",
            "target": "24:b2:b9:54:44:82",
            "context": "File",
            "status": "read",
            "created_at": "2025-10-13 01:00:25",
            "file_id": 56,
            "target_name": "张云龙(Mac)",
            "file": {
                "id": 56,
                "origin_name": "【小牛快跑-11.57元-1个行程】高德打车电子发票.pdf",
                "filename": "d3904f79-1c11-406b-bfed-58ca168f0192.pdf",
                "size": 59299,
                "origin_path": "/Users/zyl/Downloads/【小牛快跑-11.57元-1个行程】高德打车电子发票.pdf",
                "created_at": "2025-10-13 01:00:25",
                "progress": 100
            }
        },
    ]}
    """
    try:
        data = get_user_message_history(app.state.db, app_logger, {"id_1": id_1, "id_2": id_2})
        return {"message": "success", "data": data}
    except Exception as e:
        return {"message": "error", "details": str(e)}


# 获取下载进度
@app.get("/progress")
def get_progress(file_id: int):
    """
    获取文件上传进度
    """
    try:
        file_info = app.state.db.get_one("File", {"id": file_id})
        if file_info:
            return {"message": "success", "data": {"progress": file_info["progress"]}}
        else:
            return {"message": "error", "details": "File not found"}
    except Exception as e:
        return {"message": "error", "details": str(e)}


# 文件上传(new)
@app.post("/upload")
async def upload_test(
    file: UploadFile = File(..., max_size=MAX_UPLOAD_BYTES),
    origin_path: str = Form(...),  # 文件的原始路径
    source: str = Form(...),  # 发送者的mac_addr
    target: Optional[str] = Form(None),  # 接收者的mac_addr
    team_id: Optional[str] = Form(None),  # 接收的团队ID
):
    # 计算上传大小并进行限制检查
    total_size = file.file.seek(0, 2)
    if total_size > MAX_UPLOAD_BYTES:
        raise HTTPException(
            status_code=413,
            detail="File too large, Please upload files no larger than 100Mb.",
        )
    # 重置指针
    file.file.seek(0)

    # 生成UUID文件名，保留原文件扩展名
    file_extension = os.path.splitext(file.filename)[1] if file.filename else ""
    uuid_filename = str(uuid.uuid4()) + file_extension
    file_path = os.path.join(UPLOAD_DIR, uuid_filename)
    tmp_path = f"{file_path}.part"

    # 写入记录
    file_id = app.state.db.insert_one(
        "File",
        {
            "origin_name": file.filename,
            "filename": uuid_filename,
            "origin_path": origin_path,
            "size": total_size,
            "progress": 0,
        },
    )
    # 获取目标用户信息

    # 通过分片写入文件
    bytes_read = 0

    try:
        with open(tmp_path, "wb") as buffer:
            while True:
                chunk = await file.read(CHUNK_SIZE)
                if not chunk:
                    # 上传完成，更新进度为100%
                    app.state.db.update_one(
                        "File",
                        {
                            "progress": 100,
                        },
                        {"id": file_id},
                    )
                    break

                buffer.write(chunk)
                bytes_read += len(chunk)
                progress = min(int(bytes_read * 100 / total_size), 100)
                # update progress
                app.state.db.update_one(
                    "File",
                    {
                        "progress": progress,
                    },
                    {"id": file_id},
                )

        os.replace(tmp_path, file_path)

        if target:
            await send_msg_to_user(
                app.state.db,
                app_logger,
                app.state.manager,
                {
                    "source": source,
                    "target": target,
                    "context_type": "file",
                    "context": {
                        "filename": uuid_filename,
                        "size": total_size,
                        "origin_name": file.filename,
                        "origin_path": origin_path,
                        "file_id": file_id,
                    },
                },
            )

        if team_id:
            # 群消息
            await send_msg_to_team(
                app.state.db,
                app_logger,
                app.state.manager,
                {
                    "source": source,
                    "team_id": int(team_id),
                    "context_type": "file",
                    "context": {
                        "filename": uuid_filename,
                        "size": total_size,
                        "origin_name": file.filename,
                        "origin_path": origin_path,
                        "file_id": file_id,
                    },
                },
            )

        return {"message": "success", "data": {"file_id": file_id}}

    except Exception:
        # 失败回调并清理临时文件
        try:
            if os.path.exists(tmp_path):
                os.remove(tmp_path)
        finally:
            app.state.db.update_one(
                "File",
                {
                    "progress": 0,
                },
                {"id": file_id},
            )
        raise HTTPException(status_code=500, detail="Upload failed")


def get_file_meta(file_id: int):
    file_info = app.state.db.get_one("File", {"id": file_id})
    if not file_info:
        raise HTTPException(status_code=404, detail="File not found")

    meta = {
        "path": os.path.join(UPLOAD_DIR, file_info.get("filename")),
        "name": file_info.get("origin_name") or file_info.get("filename"),
        "size": file_info.get("size"),
    }

    path = meta["path"]
    if not os.path.isfile(path):
        raise HTTPException(status_code=404, detail="File not found")

    return meta


def iter_file_chunks(path: str, chunk_size: int = 1024 * 1024):
    with open(path, "rb") as file:
        while True:
            chunk = file.read(chunk_size)
            if not chunk:
                break
            yield chunk


@app.get("/download")
async def download(file_id: int = Query(..., ge=1)):
    """下载文件并返回进度"""
    try:
        meta = get_file_meta(file_id)
        headers = {
            "Content-Length": str(meta["size"]),
            "Content-Disposition": f'attachment; filename="{quote(meta["name"])}"',
        }

        return StreamingResponse(
            iter_file_chunks(meta["path"]),
            media_type="application/octet-stream",
            headers=headers,
        )
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Download failed: {str(e)}")


async def heartbeat_checker(manager, logger):
    while True:
        try:
            await asyncio.sleep(30)
            current_time = int(time.time())
            for socket_id, last_active in manager.last_activate.items():
                if current_time - last_active > 60 * 5:
                    logger.info(f"断开不活跃连接: {socket_id}")
                    await manager.disconnect(socket_id)
        except asyncio.CancelledError:
            break
        except Exception as e:
            logger.error(f"心跳检查器异常: {e}")

# WebSocket Function
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket, username, mac_addr):
    socket_id = None
    try:
        # 接入socket
        socket_id = await app.state.manager.connect(websocket, username, mac_addr)
        app_logger.info(f"{username} {mac_addr} {socket_id} 接入websocket服务")

        last_active = time.time()
        while True:
            # 收到来自客户端的消息
            text = await websocket.receive_text()
            data = json.loads(text)
            app_logger.info(f"收到来自 {socket_id} 的消息: {data}")

            # 给指定用户发送消息
            if data["category"] == "message":
                await send_msg_to_user(app.state.db, app_logger, app.state.manager, data)

            # 发送群聊消息
            elif data["category"] == "team_message":
                await send_msg_to_team(app.state.db, app_logger, app.state.manager, data)
            # 添加好友
            elif data["category"] == "add_friend":
                await add_friend_request(app.state.db, app_logger, app.state.manager, data)
            # 处理心跳保持(客户端发送ping)
            elif data["category"] == "ping":
                await app.state.manager.update_last_activate(socket_id)
                if socket_id in app.state.manager.active_connections:
                    await app.state.manager.send2client(
                        json.dumps(
                            {
                                "category": "pong",
                                "timestamp": int(time.time()),
                            },
                            ensure_ascii=False,
                        ),
                        app.state.manager.active_connections[socket_id]
                    )

                # # 心跳保持
                # if int(time.time()) - last_active > 60:
                #     # 主动断开
                #     await app.state.manager.disconnect(socket_id)
                #     app_logger.info(f"WebSocket {socket_id} 服务端主动断开")
                #     break
                # else:
                #     # 更新最后活跃时间
                #     last_active = time.time()

    except WebSocketDisconnect:
        if socket_id:
            await app.state.manager.disconnect(socket_id)
            app_logger.info(f"WebSocket {socket_id} 客户端主动断开")

    except Exception as e:
        app_logger.error(f"WebSocket Error: {str(e)}")
        if socket_id:
            await app.state.manager.disconnect(socket_id)


@app.get("/team")
def get_team(team_id: int = Query(..., gt=0)):
    """
    根据Team ID查询team信息

    参数:
        team_id (int, optional): _description_. Defaults to Query(..., gt=0).

    返回示例:
    {
        "message": "success",
        "data": {
            "id": 2,
            "name": "test2",
            "created_at": "2025-10-10 09:19:05",
            "members": [
                {
                    "id": 11,
                    "user_id": 2,
                    "team_id": 2,
                    "created_at": "2025-10-13 12:02:28",
                    "user_name": "张云龙(Mac)",
                    "user_mac_addr": "ba:4a:9a:67:c0:69",
                    "user_socket_id": "0f850596-92c6-4936-b8c7-5db6a6d5dc9e",
                    "user_status": "offline"
                },
                {
                    "id": 12,
                    "user_id": 3,
                    "team_id": 2,
                    "created_at": "2025-10-13 12:02:28",
                    "user_name": "test",
                    "user_mac_addr": "123",
                    "user_socket_id": "456",
                    "user_status": "offline"
                }
            ]
        }
    }
    """
    try:
        data = get_team_info(app.state.db, app_logger, team_id)
        return {"message": "success", "data": data}
    except Exception as e:
        app_logger.error(e)
        return {"message": "error", "details": str(e)}


@app.get("/team/message")
def team_create(mac_addr: str, team_id: int = Query(..., gt=0)):
    """
    获取群聊消息

    参数:
        mac_addr (str): 用户的MAC地址
        team_id (int, optional): 群聊ID.

    返回示例：
    {
        "message": "success",
        "data": [
            {
                "id": 1,
                "team_id": 5,
                "user_id": 2,
                "context": "hello",
                "file_id": null,
                "created_at": "2025-10-12 15:39:00",
                "file_origin_name": null,
                "file_name": null,
                "file_size": null,
                "file_origin_path": null,
                "sender_name": "张云龙(Mac)",
                "sender_mac": "ba:4a:9a:67:c0:69"
            },
            {
                "id": 18,
                "team_id": 5,
                "user_id": 1,
                "context": "File",
                "file_id": 55,
                "created_at": "2025-10-13 00:20:20",
                "file_origin_name": "实验报告_GO富集分析_20251010_103543.pdf",
                "file_name": "a96a3874-6e2e-4a05-9539-19000685567f.pdf",
                "file_size": 869884,
                "file_origin_path": "C:/Users/Yunlong/Downloads/实验报告_GO富集分析_20251010_103543.pdf",
                "sender_name": "张云龙(Win)",
                "sender_mac": "24:b2:b9:54:44:82"
            },
        ]
    }
    """
    try:
        data = get_team_message(app.state.db, app_logger, {"team_id": team_id, "mac_addr": mac_addr})
        return {"message": "success", "data": data}
    except Exception as e:
        app_logger.error(e)
        return {"message": "error", "details": str(e)}


@app.post("/team")
def team_create(request: CreateTeamRequest):
    """
    创建Team，包括名称和相关人员的ID

    参数:
    - name: str (群聊名称)
    - users: List[str] (成员的mac地址)

    返回示例：
    {
        "message": "success",
        "data": { "count": 5 }  # 成功添加的成员数量
    }
    """
    try:
        data = create_team(app.state.db, app_logger, request)
        return {"message": "success", "data": data}
    except Exception as e:
        app_logger.error(e)
        return {"message": "error", "details": str(e)}


@app.get("/user/teams")
def user_teams(user_id: int):
    """
    获取用户所有Team（废弃）

    Args:
        request (UpdateTeamRequest): _description_
    """
    try:
        data = get_user_teams(app.state.db, app_logger, user_id)
        return {"message": "success", "data": data}
    except Exception as e:
        app_logger.error(e)
        return {"message": "error", "details": str(e)}


@app.post("/team/{team_id}")
def team_update(team_id: int, request: UpdateTeamRequest):
    """
    更新Team信息（Team名称和成员）

    参数：
    - team_id: 群ID
    - team_name: Optional[str] 群名称
    - users: Optional[List[str]] 群成员的mac地址

    返回示例：
    {
        "message": "success",
        "data": {"team_id": team_id}
    }

    """
    try:
        data = update_team(app.state.db, app_logger, team_id, request)
        return {"message": "success", "data": data}
    except Exception as e:
        app_logger.error(e)
        return {"message": "error", "details": str(e)}


@app.post("/exit/team")
def exit_team(request: ExitTeamRequest):
    """
    退出群聊

    参数：
    - mac_addr: str (用户的MAC地址)
    - team_id: int (群ID)

    返回示例：
    {
        "message": "success"
    }
    """
    try:
        user_info = app.state.db.get_one("User", {"mac_addr": request.mac_addr})
        if user_info:
            app.state.db.delete_one(
                "User_Team",
                {"team_id": request.team_id, "user_id": user_info.get("id")},
            )
            return {"message": "success"}
        else:
            return {"message": "error", "details": "用户不存在"}

    except Exception as e:
        app_logger.error(e)
        return {"message": "error", "details": str(e)}


# mobile user api
@app.post("/v1/mobile/sign_up")
def sign_up(request: MobileUserRequest):
    """
    注册账号
    """
    try:
        data = mobile_user_sign_up(app.state.db, app_logger, request)
        return {"message": "success", "data": data}
    except Exception as e:
        return {"message": "error", "details": str(e)}


@app.post("/v1/mobile/sign_in")
def sign_in(request: MobileUserRequest):
    """
    登录账号
    """
    try:
        data = mobile_user_sign_in(app.state.db, app_logger, request)
        return {"message": "success", "data": data}
    except Exception as e:
        return {"message": "error", "details": str(e)}


@app.post("/v1/mobile/update")
def mobile_update(request: UpdateMobileUserRequest):
    """
    修改账号信息
    """
    try:
        data = mobile_user_update(app.state.db, app_logger, request)
        return {"message": "success", "data": data}
    except Exception as e:
        return {"message": "error", "details": str(e)}


if __name__ == "__main__":
    # 启动服务（指定端口和主机，允许外部访问）
    # parse command line arguments
    parser = argparse.ArgumentParser()
    parser.add_argument("--port", type=int, default=8000, help="端口号，默认8000")
    args = parser.parse_args()

    # initial
    os.makedirs(UPLOAD_DIR, exist_ok=True)

    # 创建logs目录
    log_dir = "./logs"
    os.makedirs(log_dir, exist_ok=True)

    # start the FastAPI app
    uvicorn.run(
        app,
        host="0.0.0.0",
        port=args.port,
        log_level="info",
        log_config={
            "version": 1,
            "disable_existing_loggers": False,
            "formatters": {
                "default": {
                    "()": "uvicorn.logging.DefaultFormatter",
                    "fmt": "%(levelprefix)s %(message)s",
                    "use_colors": False,
                },
                "access": {
                    "()": "uvicorn.logging.AccessFormatter",
                    "fmt": '%(levelprefix)s %(client_addr)s - "%(request_line)s" %(status_code)s',
                    "use_colors": False,
                },
            },
            "handlers": {
                "default": {
                    "formatter": "default",
                    "class": "logging.handlers.TimedRotatingFileHandler",
                    "filename": os.path.join(log_dir, "server.log"),
                    "when": "midnight",
                    "interval": 1,
                    "backupCount": 14,
                    "encoding": "utf-8",
                },
                "access": {
                    "formatter": "access",
                    "class": "logging.handlers.TimedRotatingFileHandler",
                    "filename": os.path.join(log_dir, "access.log"),
                    "when": "midnight",
                    "interval": 1,
                    "backupCount": 14,
                    "encoding": "utf-8",
                },
            },
            "loggers": {
                "": {"handlers": ["default"], "level": "INFO"},
                "uvicorn.error": {"level": "INFO"},
                "uvicorn.access": {
                    "handlers": ["access"],
                    "level": "INFO",
                    "propagate": False,
                },
            },
        },
    )
    app_logger.info(f"Server is running on http://localhost:{args.port}")
